package other.edan.erp.k3;


import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.ScheduleJob;
import com.rkhd.platform.sdk.api.annotations.RequestMethod;
import com.rkhd.platform.sdk.api.annotations.RestApi;
import com.rkhd.platform.sdk.api.annotations.RestMapping;
import com.rkhd.platform.sdk.api.annotations.RestQueryParam;
import com.rkhd.platform.sdk.data.model.*;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.AsyncTaskException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.model.OperateResult;
import com.rkhd.platform.sdk.param.ScheduleJobParam;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.edan.erp.apitool.EdanK3Utils;
import other.edan.erp.utils.HCXObjectService;
import other.edan.erp.utils.ResultBody;
import other.edan.erp.utils.ResultVo;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 同步k3销售发票
 * @Author 黎炎松
 * 2024-11-14 16:56
 */
@RestApi(baseUrl = "/edan/salesInvoice")
public class SyncSaleInvoice extends SyncSuper implements ScheduleJob, FutureTask {
    private static XoqlService xoqlService = XoqlService.instance();
    private static final Logger LOGGER = LoggerFactory.getLogger();
    private static String LOGGER_MSG = "同步K3销售发票数据 ==> ";

    // 执行定时任务
    @Override
    public void execute(ScheduleJobParam scheduleJobParam) {
        LOGGER.debug(LOGGER_MSG + " 执行定时任务开始");
        try {
            String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
            LOGGER.info(LOGGER_MSG + "异步ID:" + messageId);
        } catch (Exception e) {
            LOGGER.error(LOGGER_MSG + " ----- 发生异常：" + e.getMessage());
        }
    }

    // 执行异步函数
    @Override
    public void execute(String s) throws ScriptBusinessException {
        if (StringUtils.isNotBlank(s)) {
            String[] split = s.split(",");
            startSyncSaleInvoice(1,"", split[0], split[1]);
        } else {
            startSyncSaleInvoice(2,"", "", "");
        }
    }

    /**
     * 根据产品编号手动触发同步
     * @param
     * @return
     */
    @RestMapping(value = "/syncById", method = RequestMethod.POST)
    public ResultVo syncById(@RestQueryParam(name = "id") Long invoiceId, @RestQueryParam(name = "billNo") String billNo) {

        LOGGER.debug("根据编号手动触发同步: billNo " + billNo);
        if (StringUtils.isNotBlank(billNo)) {
            return startSyncSaleInvoice(1, billNo, "", "");
        }

        // 获取编码
        LOGGER.debug("根据编号手动触发同步: invoiceId " + invoiceId);
        SalesInvoice__c salesInvoice = new SalesInvoice__c();
        salesInvoice.setId(invoiceId);
        salesInvoice = HCXObjectService.get(salesInvoice);
        String outNo = salesInvoice.getName();

        LOGGER.debug("根据编号手动触发同步: " + outNo);
        return startSyncSaleInvoice(1, outNo, "", "");
    }

    /**
     * 手动触发销售发票同步
     * @param
     * @return
     */
    @RestMapping(value = "/handerSync", method = RequestMethod.POST)
    public ResultVo handerSync() throws AsyncTaskException {
        LOGGER.debug("手动触发销售发票同步");
        String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
        LOGGER.info(LOGGER_MSG + "异步ID:" + messageId);
        return ResultVo.success("开始同步");
    }

    /**
     * 手动根据日期同步销售发票数据
     * @param
     * @return
     */
    @RestMapping(value = "/handByDate", method = RequestMethod.GET)
    public ResultVo handByDate(@RestQueryParam(name = "startDate") String startDate, @RestQueryParam(name = "endDate") String endDate) throws AsyncTaskException {
        LOGGER.debug(LOGGER_MSG + "手动根据日期同步销售发票数据 startDate = " + startDate);
        if (StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) {
            return ResultVo.error("同步日期不可为空");
        }

        String messageId = FutureTaskService.instance().addFutureTask(getClass(), startDate + "," + endDate);
        LOGGER.info(LOGGER_MSG + "异步ID:" + messageId);
        return ResultVo.success("开始同步");
    }


    public static void main(String[] args) {
        HCXObjectService.isLocal = true;

        SyncSaleInvoice syncSaleInvoice = new SyncSaleInvoice();
        syncSaleInvoice.startSyncSaleInvoice(1,"", "2025-01-25 00:00:00", "2025-01-31 23:59:59");
    }

    /**
     * 开始同步销售发票
     * @param syncType 同步类型 1: 初始化全量同步  2: 后续定期增量同步 (只有定时同步入参2，其他入参1)
     * @param icsalebillNo
     * @return
     */
    public ResultVo startSyncSaleInvoice(int syncType, String icsalebillNo, String propStartDate, String propEndDate) {
        try {
            LOGGER.debug(LOGGER_MSG + "处理开始");

            // 从数据配置表中获取数据
            SyncConfig__c syncConfig = getSyncConfig("K3_XXFP");

            String startDate = syncConfig.getAttribute("startDate");
            String endDate = syncConfig.getAttribute("endDate");
            if (StringUtils.isNotBlank(propStartDate) && StringUtils.isNotBlank(propEndDate)) {
                startDate = propStartDate;
                endDate = propEndDate;
            }

            // 设置参数
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("page", "1");
            paramsMap.put("pageSize", "5000");
            // 销售销售发票编号如果不为空 则只查询单条数据
            if (StringUtils.isNotBlank(icsalebillNo)) {
                paramsMap.put("icsalebillNo", icsalebillNo);
            } else {
                // 后续增量同步使用  updateStartDate updateEndDate
                paramsMap.put(syncType == 2 ? "updateStartDate" : "StartDate", startDate); // StartDate EndDate
                paramsMap.put(syncType == 2 ? "updateEndDate" : "EndDate", endDate);
            }
            LOGGER.debug(LOGGER_MSG + " paramsMap: " + paramsMap);

            // 发送请求获取数据
            ResultBody response = EdanK3Utils.sendGet(paramsMap, EdanK3Utils.GET_SALES_INVOICE, "");
            if (!Objects.equals(response.getCode(), "200")) {
                LOGGER.debug(LOGGER_MSG + "查询k3数据异常: " + response.getMessage());
                return ResultVo.error("查询k3数据异常: " + response.getMessage());
            }

            // 获取数据 判断是否有值
            JSONObject result = (JSONObject) response.getResult();
            List<JSONObject> k3SearchData = JSONObject.parseArray(result.getJSONArray("ICSaleInfos").toJSONString(), JSONObject.class);
            LOGGER.debug(LOGGER_MSG + "查询返回的数据: " + k3SearchData.size());
            if (k3SearchData.size() <= 0) {
                LOGGER.debug(LOGGER_MSG + "暂无需要处理的数据");
                // 同步修改配置表
                if (syncType == 2) upSyncConfig(syncConfig);
                return ResultVo.success();
            }

            // 按照单号进行分组
            List<JSONObject> k3DataList = new ArrayList<>();
            Set<String> k3DelBillNo = new HashSet<>();
            k3SearchData.stream().forEach(v -> {
                if (StringUtils.isNotBlank(v.getString("fdeleteDate"))) {
                    k3DelBillNo.add("'" + v.getString("fbillNo") + "'");
                } else {
                    k3DataList.add(v);
                }
            });
            Map<String, List<JSONObject>> invoiceListMap = k3DataList.stream().collect(Collectors.groupingBy(e -> e.getString("fbillNo")));
            LOGGER.debug(LOGGER_MSG + "invoiceListMap: " + invoiceListMap);

            // 先处理删除的数据
            delInvoiceByNo(StringUtils.join(k3DelBillNo, ","));

            // 获取系统中存在的销售发票
            Map<String, Long> crmSalesInvoiceMap = getCrmDataMap("saleInvoice", "fbillNo", k3DataList);

            // 获取系统中的销售发票明细 (明细标识：主表id + 明细序号)
            String filterVals = k3DataList.stream().map(v -> "'" + v.getString("finterID") + v.getString("fentryID") + "'").distinct().collect(Collectors.joining(","));
            String sql = String.format("select id,edanId__c from salesInvoiceDetails__c where edanId__c in (%s)", filterVals);
            Map<String, Long> invoiceDetailMap = xoqlService.query(sql).getRecords().stream().collect(Collectors.toMap(e -> e.getString("edanId__c"), e1 -> e1.getLong("id"), (e, e1) -> e));
            LOGGER.debug(LOGGER_MSG + "invoiceDetailMap: " + invoiceDetailMap.size());

            // 获取系统中的客户
            Map<String, Long> crmAccountMap = getCrmDataMap("account", "customerCode", k3DataList);

            // 获取系统中的用户
            Map<String, Long> crmUserMap = getCrmDataMap("user", "salesman", k3DataList);

            // 获取系统中的订单
            Map<String, Long> crmOrderMap = getCrmDataMap("k3CodeOrder", "orderBillNo", k3DataList);

            // 获取系统中的产品
            Map<String, Long> crmProductMap = getCrmDataMap("product", "fnumber", k3DataList);

            // 获取系统中的销售出库
            Map<String, Long> crmSalOutMap = getCrmDataMap("saleOut", "stockBillNo", k3DataList);

            // 获取系统中销售出库明细
            filterVals = k3DataList.stream().map(v -> "'" + v.getString("stockInterID") + v.getString("stockEntryID") + "'").distinct().collect(Collectors.joining(","));
            sql = String.format("select id,edanId__c from salesOutReceiptDetails__c where edanId__c in (%s)", filterVals);
            Map<String, Long> outDetailMap = xoqlService.query(sql).getRecords().stream().collect(Collectors.toMap(e -> e.getString("edanId__c"), e1 -> e1.getLong("id")));
            LOGGER.debug(LOGGER_MSG + "outDetailMap: " + outDetailMap.size());

            // 获取新增、修改的数据
            List<SalesInvoice__c> upMasterList = new ArrayList<>(); // 修改主表
            List<SalesInvoiceDetails__c> upDetailList = new ArrayList<>(); // 修改详情
            for (String fbillNo : invoiceListMap.keySet()) {
                // 明细数据
                List<JSONObject> detailList = invoiceListMap.get(fbillNo);
                if (detailList.size() <= 0) {
                    continue;
                }

                // 处理出库
                JSONObject masterObj = detailList.get(0); // 出库数据
                String finterID = masterObj.getString("finterID");

                SalesInvoice__c salesInvoice = new SalesInvoice__c();
                salesInvoice.setEntityType(3533385747454552L);
                salesInvoice.setDataSource__c(2); // 数据来源 1: 系统  2: k3  3: 其他
                salesInvoice.setEdanId__c(finterID);
                salesInvoice.setName(fbillNo); // 编号
                salesInvoice.setOrderNumText__c(masterObj.getString("orderBillNo")); // 订单号文本
                salesInvoice.setContractCode__c(masterObj.getString("contractNumber")); // 正式合同编号
                salesInvoice.setSaleStyle__c(masterObj.getString("saleStyle")); // 销售方式
                salesInvoice.setCustomerName__c(masterObj.getString("customer")); // 购货单位名称
                salesInvoice.setCustomerCode__c(masterObj.getString("customerCode")); // 购货单位代码
                salesInvoice.setInvoiceDate__c(getDateVal(masterObj.getString("fdate"), 1)); // 发票日期
                salesInvoice.setAttribute("exchangeRate__c", masterObj.getString("fexchangeRate")); // 汇率
                salesInvoice.setSalesman__c(crmUserMap.get(masterObj.getString("salesman"))); // 业务员
                salesInvoice.setSection__c(masterObj.getString("fdepartment")); // 部门
                salesInvoice.setSaleStyle__c(masterObj.getString("saleStyle")); // 销售方式
                salesInvoice.setFlowNumber__c(masterObj.getString("waterNumber")); // 发票流水号
                salesInvoice.setAbstract__c(masterObj.getString("fexplanation")); // 摘要

                // 关联关系
                salesInvoice.setPurchasingUnit__c(crmAccountMap.get(masterObj.getString("customerCode"))); // 购货单位 关联关系
                salesInvoice.setOrderNum__c(crmOrderMap.get(masterObj.getString("orderBillNo"))); // 销售订单号 关联关系

                // 红蓝字标识
                String flag = masterObj.getString("flag");
                Integer flagVal = null;
                if (flag.contains("蓝")) {
                    flagVal = 1;
                } else if (flag.contains("红")) {
                    flagVal = 2;
                }
                salesInvoice.setFlag__c(flagVal);

                // 判断系统中是否存在，存在则更新
                System.out.println("salesInvoice = " + salesInvoice);
                if (crmSalesInvoiceMap.containsKey(fbillNo)) {
                    salesInvoice.setId(crmSalesInvoiceMap.get(fbillNo));
                    upMasterList.add(salesInvoice);
                    // 进行更新
                    if (upMasterList.size() >= 100) {
                        HCXObjectService.updateBatch(upMasterList);
                        upMasterList.clear();
                    }
                } else {
                    // 新增
                    OperateResult insert = HCXObjectService.insert(salesInvoice);
                    if (!insert.getSuccess()) {
                        LOGGER.error(LOGGER_MSG + "新增发票失败 fbillNo: " + fbillNo);
                        continue;
                    }
                    salesInvoice.setId(insert.getDataId());
                }

                // 处理明细数据 (不考虑k3后续同步删除订单明细的情况)
                for (JSONObject detailObj : detailList) {
                    List<SalesInvoiceDetails__c> addDetailList = new ArrayList<>(); // 新增详情

                    String fentryID = detailObj.getString("fentryID");
                    String edanId = finterID + fentryID; // 唯一标识: finterID + fentryID

                    // 明细对象
                    SalesInvoiceDetails__c salesInvoiceDetails = new SalesInvoiceDetails__c();
                    salesInvoiceDetails.setEntityType(3533387730180703L);
                    salesInvoiceDetails.setSalesInvoice__c(salesInvoice.getId()); // 主表
                    salesInvoiceDetails.setEdanId__c(edanId); // 数据id
                    salesInvoiceDetails.setName(fentryID); // 编号
                    salesInvoiceDetails.setProductNameText__c(detailObj.getString("productName")); // 产品名称
                    salesInvoiceDetails.setProductCodeText__c(detailObj.getString("fnumber")); // 产品代码
                    salesInvoiceDetails.setModel__c(detailObj.getString("model")); // 规格型号
                    salesInvoiceDetails.setOrderCodeText__c(detailObj.getString("orderBillNo")); // 订单单号
                    salesInvoiceDetails.setCorrespondingInvoiceNum__c(detailObj.getString("ffpkName")); // 发票库对应码
                    salesInvoiceDetails.setCorrespondingInvoiceNumCode__c(detailObj.getString("ffpkNumber")); // 发票库对应代码
                    salesInvoiceDetails.setUnit__c(detailObj.getString("unit")); // 单位
                    salesInvoiceDetails.setQuantity__c(detailObj.getDouble("fqty")); // 数量
                    salesInvoiceDetails.setTaxUnitPrice__c(detailObj.getDouble("fauxTaxPrice")); // 含税单价
                    salesInvoiceDetails.setAmount__c(detailObj.getDouble("fallAmount")); // 价税合计
                    salesInvoiceDetails.setTaxRate__c(bgDivide(detailObj.getDouble("ftaxRate"), 100)); // 税率

                    // 关联关系
                    salesInvoiceDetails.setOrderCode__c(crmOrderMap.get(detailObj.getString("orderBillNo"))); // 订单单号
                    salesInvoiceDetails.setProductName__c(crmProductMap.get(detailObj.getString("fnumber"))); // 产品名称

                    // 出库单、出库单明细
                    salesInvoiceDetails.setSalesOutReceipt__c(crmSalOutMap.get(detailObj.getString("stockBillNo")));
                    String outDetailId = detailObj.getString("stockInterID") + detailObj.getString("stockEntryID");
                    salesInvoiceDetails.setSalesOutReceiptDetails__c(outDetailMap.get(outDetailId));
                    salesInvoiceDetails.setSalesOutNo__c(detailObj.getString("stockBillNo")); // 出库 文本
                    salesInvoiceDetails.setSalesOutDetailNo__c(detailObj.getString("stockBillNo") + "-" + detailObj.getString("stockEntryID")); // 出库明细 文本


                    // 判断是新增还是修改
                    if (invoiceDetailMap.containsKey(edanId)) {
                        salesInvoiceDetails.setId(invoiceDetailMap.get(edanId));
                        upDetailList.add(salesInvoiceDetails);
                    } else {
                        addDetailList.add(salesInvoiceDetails);
                    }

                    // 进行新增、编辑操作
                    HCXObjectService.insertBatch(addDetailList);
                    if (upDetailList.size() > 100) {
                        HCXObjectService.updateBatch(upDetailList);
                        upDetailList.clear();
                    }
                }
            }

            // 进行批量、新增更新
            HCXObjectService.updateBatch(upMasterList);
            HCXObjectService.updateBatch(upDetailList);

            // 更新同步配置
            if (syncType == 2) upSyncConfig(syncConfig);

            LOGGER.debug(LOGGER_MSG + "处理成功");
            return ResultVo.success();
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.debug(LOGGER_MSG + "处理异常:" + e.getMessage());
            return ResultVo.error("处理异常: " + e.getMessage());
        }
    }

    /**
     * 根据编号删除发票
     * @param k3DelBillNo
     * @throws ApiEntityServiceException
     */
    public void delInvoiceByNo(String k3DelBillNo) throws ApiEntityServiceException {
        LOGGER.debug(LOGGER_MSG + " k3DelBillNo = " + k3DelBillNo);
        if (StringUtils.isBlank(k3DelBillNo)) {
            LOGGER.debug(LOGGER_MSG + " 没有需要删除的发票数据");
            return;
        }

        // 获取发票 id
        String sql = String.format("select id from salesInvoice__c where name in (%s)", k3DelBillNo);
        List<JSONObject> masterList = xoqlService.query(sql).getRecords();

        // 删除发票
        List<SalesInvoice__c> delInvoiceList = masterList.stream().map(v -> {
            SalesInvoice__c delInvoice = new SalesInvoice__c();
            delInvoice.setId(v.getLong("id"));
            return delInvoice;
        }).collect(Collectors.toList());
        HCXObjectService.deleteBatch(delInvoiceList);
    }


}
